package day04.tx.app.service;

import day04.tx.app.mapper.AccountMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class Service7 {

    private static final Logger logger = LoggerFactory.getLogger(Service7.class);

    @Autowired
    private AccountMapper accountMapper;

    @Transactional(rollbackFor = Exception.class)
    // public synchronized void transfer（）
    // 问题描述
    // 对事物方法加锁，并不能解决并发问题
    // 原因：事物方法使用的是 aop 环绕通知，commit 方法在事物方法之后
    // 所以当前方法释放对象锁之后，事物也不是立即能提交，
    // 个人理解2： 即使能立即提交，发送网络请求也需要时间，但是另外线程已经拿到锁，
    // 有一定几率会出现 此线程的查询 先于上个 线程的提交，所以导致获取的还是老数据
    public void transfer(int from, int to, int amount) {
        // 问题原因：并发情况下，多个线程查询的结果返回一致
        int fromBalance = accountMapper.findBalanceBy(from);
        logger.debug("更新前查询余额为: {}", fromBalance);
        if (fromBalance - amount >= 0) {
            accountMapper.update(from, -1 * amount);
            accountMapper.update(to, amount);
        }
    }

    public int findBalance(int accountNo) {
        return accountMapper.findBalanceBy(accountNo);
    }
}
